
#include "EntitySystem.h"

#include <ALittleClient/ScriptSystem/ScriptSystem.h>
#include <ALittleClient/LogSystem/LogSystem.h>
#include <ALittleClient/RenderSystem/RenderSystem.h>
#include <ALittleClient/RenderSystem/EntitySystem/CameraSystem.h>

#include <math.h>

#include "Entity.h"
#include "CommonEntity.h"
#include "CommonEntities.h"
#include "QuadEntity.h"
#include "ImageEntity.h"

namespace ALittle
{

EntitySystem::EntitySystem()
{ }

EntitySystem::~EntitySystem() {}

EntitySystem& EntitySystem::Instance()
{
	static EntitySystem instance;
	return instance;
}

void EntitySystem::Setup()
{
}

void EntitySystem::Shutdown()
{
}

//===============================================================================
void EntitySystem::RegisterToScript()
{
	g_ScriptSystem.RegisterClass2Script<Entity>("GlobalEntity");

	g_ScriptSystem.RegisterClass2Script<CommonEntity>("GlobalCommonEntity");

	g_ScriptSystem.RegisterClass2Script<CommonEntities>("GlobalCommonEntities")
			.Constructor()
			.AddMemberFunction("SetTransX", &CommonEntities::SetTransX)
			.AddMemberFunction("SetTransY", &CommonEntities::SetTransY)
			.AddMemberFunction("SetTransZ", &CommonEntities::SetTransZ)
			.AddMemberFunction("SetScaleX", &CommonEntities::SetScaleX)
			.AddMemberFunction("SetScaleY", &CommonEntities::SetScaleY)
			.AddMemberFunction("SetScaleZ", &CommonEntities::SetScaleZ)
			.AddMemberFunction("SetRotateX", &CommonEntities::SetRotateX)
			.AddMemberFunction("SetRotateY", &CommonEntities::SetRotateY)
			.AddMemberFunction("SetRotateZ", &CommonEntities::SetRotateZ)
			.AddMemberFunction("AddChild", &CommonEntities::AddChild)
			.AddMemberFunction("RemoveChild", &CommonEntities::RemoveChild)
			.AddMemberFunction("SetVisible", &CommonEntities::SetVisible);

	g_ScriptSystem.RegisterClass2Script<QuadEntity>("GlobalQuadEntity")
			.Constructor()
			.AddMemberFunction("SetTransX", &QuadEntity::SetTransX)
			.AddMemberFunction("SetTransY", &QuadEntity::SetTransY)
			.AddMemberFunction("SetTransZ", &QuadEntity::SetTransZ)
			.AddMemberFunction("SetScaleX", &QuadEntity::SetScaleX)
			.AddMemberFunction("SetScaleY", &QuadEntity::SetScaleY)
			.AddMemberFunction("SetScaleZ", &QuadEntity::SetScaleZ)
			.AddMemberFunction("SetRotateX", &QuadEntity::SetRotateX)
			.AddMemberFunction("SetRotateY", &QuadEntity::SetRotateY)
			.AddMemberFunction("SetRotateZ", &QuadEntity::SetRotateZ)
			.AddMemberFunction("SetRed", &QuadEntity::SetRed)
			.AddMemberFunction("SetGreen", &QuadEntity::SetGreen)
			.AddMemberFunction("SetBlue", &QuadEntity::SetBlue)
			.AddMemberFunction("SetAlpha", &QuadEntity::SetAlpha)
			.AddMemberFunction("SetVisible", &QuadEntity::SetVisible);

	g_ScriptSystem.RegisterClass2Script<ImageEntity>("GlobalImageEntity")
		.Constructor()
		.AddMemberFunction("SetTransX", &ImageEntity::SetTransX)
		.AddMemberFunction("SetTransY", &ImageEntity::SetTransY)
		.AddMemberFunction("SetTransZ", &ImageEntity::SetTransZ)
		.AddMemberFunction("SetScaleX", &ImageEntity::SetScaleX)
		.AddMemberFunction("SetScaleY", &ImageEntity::SetScaleY)
		.AddMemberFunction("SetScaleZ", &ImageEntity::SetScaleZ)
		.AddMemberFunction("SetRotateX", &ImageEntity::SetRotateX)
		.AddMemberFunction("SetRotateY", &ImageEntity::SetRotateY)
		.AddMemberFunction("SetRotateZ", &ImageEntity::SetRotateZ)
		.AddMemberFunction("SetRed", &ImageEntity::SetRed)
		.AddMemberFunction("SetGreen", &ImageEntity::SetGreen)
		.AddMemberFunction("SetBlue", &ImageEntity::SetBlue)
		.AddMemberFunction("SetAlpha", &ImageEntity::SetAlpha)
		.AddMemberFunction("SetTexture", &ImageEntity::SetTexture)
		.AddMemberFunction("SetTextureCoord", &ImageEntity::SetTextureCoord)
		.AddMemberFunction("SetVisible", &ImageEntity::SetVisible);

	g_ScriptSystem.RegisterClass2Script<EntitySystem>("SailEntitySystem")
			.AddMemberFunction("AddChild", &EntitySystem::AddChild)
			.AddMemberFunction("RemoveChild", &EntitySystem::RemoveChild);

	g_ScriptSystem.SetValue("Global_EntitySystem", &g_EntitySystem);

	g_CameraSystem.RegisterToScript();
}
//===============================================================================

#define PROJECTION_NEAR 1.0
#define PROJECTION_FAR 1000.0
#define PROJECTION_FOVY 90.0
#define PROJECTION_DEG2RAD (3.14159265 / 180)

void EntitySystem::PushProjection()
{
	// tangent of half fovY
	double tangent = tan(PROJECTION_FOVY/2.0 * PROJECTION_DEG2RAD);
	// half height of near plane
	double height = PROJECTION_NEAR * tangent;
	// half width of near plane
	double width = height * ((double)g_RenderSystem.GetWindowWidth()/(double)g_RenderSystem.GetWindowHeight());

	// params: left, right, bottom, top, near, far
	glFrustum(-width, width, -height, height, PROJECTION_NEAR, PROJECTION_FAR);
}

void EntitySystem::Render()
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	PushProjection();

	glMatrixMode(GL_MODELVIEW);
 	glLoadIdentity();

	g_CameraSystem.PushCamera();

 	m_entity_list.Render();
}

void EntitySystem::AddChild(CommonEntity* entity)
{
	m_entity_list.AddChild(entity);
}

void EntitySystem::RemoveChild(CommonEntity* entity)
{
	m_entity_list.RemoveChild(entity);
}

} // ALittle
